<?php
 /**
 * Phlux provides fluent interface functionalities to existing
 * functions and methods
 * 
 * @PHP version 5
 * @category Tool_Class
 * @package  Phlux
 * @author   Alexander Wühr <awuehr@gmail.com>
 * @license  GPLv3
 *
 */



 /**
 * Phlux provides fluent interface functionalities to existing
 * functions and methods
 * 
 * @PHP version 5
 * @category Tool_Class
 * @package  Phlux
 * @author   Alexander Wühr <awuehr@gmail.com>
 * @license  GPLv3
 *
 */
class Phlux
{
    protected $callback;
    protected $object = false;
    protected $arguments = array();

    /**
     * Constructor
     * 
     * @param mixed  $callback Object or function name (string)
     * @param string $method   method name if $callback is an object
     */
    public function __construct($callback, $method = null)
    {
        $this->callback = $callback;
        if (is_object($callback)) {
            $this->object      = $callback;
            $callback->$method = $this;
            $this->callback    = $method;
        }
    }

    /**
     * Factory method
     * 
     * @param mixed  $callback Object or function name (string)
     * @param string $method   method name if $callback is an object
     * 
     * @return Phlux
     */
    public static function factory($callback, $method = null)
    {
        return new self($callback, $method);
    }

    /**
     * Alias for Phlux::factory
     * 
     * @param mixed  $callback Object or function name (string)
     * @param string $method   method name if $callback is an object
     * 
     * @return Phlux
     */
    public static function urize($callback, $method = null)
    {
        return self::factory($callback, $method);
    }

    public function __toString()
    {
        return (string)$this->result();
    }

    public function __get($var)
    {
        if (!$this->exists($var)) throw new Exception('Unknown argument '.$var, 2);
        return $this->arguments[$var];
    }

    public function __set($var, $val)
    {
        if (!$this->exists($var)) throw new Exception('Unknown argument '.$var, 1);
        $this->arguments[$var] = $val;
    }

    protected function exists($var)
    {
        return array_key_exists($var, $this->arguments);
    }

    public function result()
    {
        $cbf    = $this->callback;
        $object = $this->object;
        return ($this->object)
            ?call_user_func_array(array($object,$cbf), $this->arguments)
            :call_user_func_array($cbf, $this->arguments);
    }

    public function arg($var)
    {
        $this->arguments[$var] = null;
        return $this;
    }

    public function with($var, $val)
    {
        $this->$var = $val;
        return $this;
    }
    
    public function andWith($var, $val)
    {
        return $this->with($var, $val);
    }

    public function __call($var, $val)
    {
        if (substr($var, 0, 4)=='with') 
            return $this->with(substr($var, 4), $val[0]);
        if (substr($var, 0, 7)=='andWith') 
            return $this->andWith(substr($var, 7), $val[0]);
        if (substr($var, 0, 3)=='get')
            return $this->arguments[substr($var, 3)];
        return $var($val);
    }
}
